package study.thread.sync;

/*
 * 1.同步方法：
 *    (1).当线程调用同步方法时，它自动获取这个方法所在的对象的内在锁；
 *    (2).方法返回时释放锁，如果发生未捕获的异常也会释放锁；
 *    
 * 2.当调用静态同步方法时，因为静态方法和类关联，线程获取这个类关联的Class对象的内在锁;
 * 
 * 3.当把synchronized放到类前面时，这个类的所有方法都是同步方法；
 * 
 * 4.线程可以获得它已经拥有的锁，即可以重入同步reentrant，这种情况通常是同步代码直接或
 * 间接的调用了也包含了同步代码的方法，并且两个代码集都使用同一个锁。可重入同步避免线程阻塞自己。
 */
public class BankAccountSync {
	private int number;
	
	//余额
	private int  balance;
	
	public int getBalance() {
		return balance;
	}

	public BankAccountSync(int number,int balance) {
		this.number = number;
		this.balance = balance;
	}
	
	//存款
	//同步方法
	public synchronized void deposit(int amount) {
		this.balance += amount;
	}
	
	//取款
	//同步语句
	public void withdraw(int amount) {
		synchronized (this) {
			this.balance -= amount;
		}
	}
	
	public static void main(String[] args) throws InterruptedException {
		BankAccountSync account = new BankAccountSync(1,1000);
		
		Thread t1 = new Thread(new Depositor(account,100),"Depositor");
		Thread t2 = new Thread(new Withdraw(account,100),"Withdraw");
		
		t1.start();
		t2.start();
		
		t1.join();
		t2.join();
		
		System.out.println(account.balance);
	}
	
	
	//静态存款内部类
	static class Depositor implements Runnable {
		BankAccountSync account;
		int amount;
		
		public Depositor(BankAccountSync account,int amount) {
			this.account = account;
			this.amount = amount;
		}
		
		public void run() {
			for (int i = 0; i < 100000; i++) {
				account.deposit(amount);
			}
		}
	}
	
	static class Withdraw implements Runnable {
		BankAccountSync account;
		int amount;
		
		public Withdraw(BankAccountSync account,int amount) {
			this.account = account;
			this.amount = amount;
		}
		
		public void run() {
			for (int i = 0; i < 100000; i++) {
				account.withdraw(amount);
			}
		}
	}
}
